import type { App } from 'vue'
import { ElLoading } from 'element-plus'
import jsCookie from 'js-cookie'
import axios from 'axios'
import { saveAs } from 'file-saver'
/**
 * token相关操作
 */
class Token {
  key: string
  constructor(key: string) {
    this.key = key
  }
  setToken(token: string) {
    return jsCookie.set(this.key, token)
  }
  getToken() {
    return jsCookie.get(this.key)
  }
  removeToken() {
    return jsCookie.remove(this.key)
  }
}
export const wrapperToken = new Token(import.meta.env.VITE_TOKEN_STR)

/**
 * 获取随机字符串
 */
export const getRandomStr = (length: number, hasNumber = true): string => {
  let result = ''
  const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  const charactersLength = hasNumber ? characters.length : characters.length - 10

  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength))
  }

  return result
}

interface LoadingConfigType {
  lock: boolean
  text: string
  background: string
  target: HTMLElement
}
/**
 * loading高阶函数
 */
export const withLoading = async (
  fn: any = () => {},
  params: any = {},
  target: undefined | string = undefined,
  text = '数据加载中...',
  bgColor = 'rgba(0,0,0,0.7)'
) => {
  let loading: any = null
  const showLoading = () => {
    const defaultOptions: LoadingConfigType = {
      lock: true,
      text,
      background: bgColor,
      target: target
        ? document.querySelector(target) ?? document.documentElement
        : document.documentElement
    }
    loading = ElLoading.service(defaultOptions)
  }
  const hideLoading = () => {
    loading?.close()
  }
  try {
    showLoading()
    return await fn(params)
  } catch (error) {
    console.log(error)
    throw error
  } finally {
    hideLoading()
  }
}
/**
 * 将{ a:1, b:2 }的对象转为'?a=1&b=2'的url字符串格式
 */
export function setObjToUrlParams(baseUrl: string, obj: any): string {
  let parameters = ''
  for (let key in obj) {
    parameters += key + '=' + encodeURIComponent(obj[key]) + '&'
  }
  parameters = parameters.replace(/&$/, '')
  return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters
}

/**
 * 将js对象转为json文件并导出
 * @param data 要导出的文件
 * @param name 文件名
 */
export function exportJsToJsonFile(data: any, name: string) {
  const jsonData = JSON.stringify(data)
  const blob = new Blob([jsonData], {
    type: 'application/json;charset=utf-8'
  })
  saveAs(blob, name + '.json')
}

/**
 * 读取本地json文件
 * @param jsonFileName json文件名
 */
export async function readLocalJsonFile(jsonFileName: string): Promise<any> {
  try {
    const response = await axios.get(
      `${import.meta.env.VITE_BASE_API === '/dev-api' ? '/public' : ''}/json/${jsonFileName}.json`
    )
    return response.data
  } catch (e) {
    console.error('读取本地json文件失败')
  }
}

/**
 * 注册组件
 */
export const withInstall = (component: any, alias?: string) => {
  const comp = component as any
  comp.install = (app: App) => {
    app.component(comp.name || comp.displayName, component)
    if (alias) {
      app.config.globalProperties[alias] = component
    }
  }
  return component as any & Plugin
}

/**
 * 读取环境变量配置
 */
export function wrapperEnv(envConf: Recordable): ImportMetaEnv {
  const ret: any = {}
  for (let envName of Object.keys(envConf)) {
    let realName =
      typeof envConf[envName] === 'string'
        ? envConf[envName].replace(/\\n/g, '\n')
        : envConf[envName]
    realName = realName === 'true' ? true : realName === 'false' ? false : realName

    if (envName === 'VITE_APP_PORT' || envName === 'VITE_REQUEST_TIMEOUT') {
      realName = Number(realName)
    }
    if (envName === 'VITE_PROXY' && realName) {
      try {
        realName = JSON.parse(realName.replace(/'/g, '"'))
      } catch (error) {
        realName = ''
      }
    }
    ret[envName] = realName
    if (typeof realName === 'string') {
      process.env[envName] = realName
    } else if (typeof realName === 'object') {
      process.env[envName] = JSON.stringify(realName)
    }
  }
  return ret
}
